k近邻法(knn)就一种基本分类与回归方法。
from scipy.spatial import minkowski_distance
def classify0(inX, dataSet, labels, k):
# dataSetSize = dataSet.shape[0]
# diffMat = np.tile(inX, (dataSetSize, 1)) - dataSet
# sqDiffMat = diffMat **2
# sqDistances = sqDiffMat.sum(axis=1)
# distances = sqDistances**0.5
# print('distances', distances)
distances = minkowski_distance(inX, dataSet) #计算inX与与dataSet各个点的距离,返回个array
sortedDistIndicies = distances.argsort() #返回排序后的元素下标
classCount = {}
for i in range(k):
voteIlabel = labels[sortedDistIndicies[i]] #获得对应的label
classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1
# 对classCount根据键值进行排序
sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)
return sortedClassCount[0][0]
# 将txt转换为矩阵
def file2matrix2(filename):
data = np.genfromtxt(filename, dtype='|U8')
returnMat = data[:, 0:-1].astype('float64')
return returnMat, data[:,-1]
# 数据进行规格化处理
def autoNorm(dataSet):
minVals = dataSet.min(0)
maxVals = dataSet.max(0)
ranges = maxVals - minVals
normDataSet = np.zeros(dataSet.shape)
m = dataSet.shape[0]
normDataSet = dataSet - np.tile(minVals, (m, 1))
normDataSet = normDataSet/np.tile(ranges, (m,1))
return normDataSet, ranges, minVals
# 这里使用了scikit-learn中的API,结果与autoNorm是一样的
def autoNorm2(dataSet):
from sklearn.preprocessing import normalize
minVals = dataSet.min(0)
maxVals = dataSet.max(0)
normDataSet = normalize(dataSet, norm='max',axis=0)
return normDataSet, maxVals-minVals, minVals
# 将txt文件转换为向量
def img2vec(filename):
rVec = np.zeros((1,1024))
f = open(filename)
for i in range(32):
line = f.readline()
for j in range(32):
rVec[0, 32*i+j] = int(line[j])
return rVec
# 对手写数字进行测试
def handwritingClassTest():
hwLabels = []
trainFileList = os.listdir('digits/trainingDigits/')
m = len(trainFileList)
trainingMat = np.zeros((m, 1024))
for i in range(m):
filename = trainFileList[i]
className = int(filename.split('_')[0])
hwLabels.append(className)
trainingMat[i,:] = img2vec('digits/trainingDigits/%s' % filename)
testFileList = os.listdir('digits/testDigits')
accuracyCount = 0.0
mTest = len(testFileList)
for i in range(mTest):
filename = testFileList[i]
className = int(filename.split('_')[0])
vecTest = img2vec('digits/testDigits/%s' % filename)
classifierResult = classify0(vecTest, trainingMat, hwLabels, 1)
if classifierResult == className:
accuracyCount += 1
print("the total accuracy rate is: %f" % (accuracyCount/mTest))
在正式进行数据挖掘之前,尤其是使用基于对象距离的 挖掘算法时,如:神经网络、最近邻分类等,必须 进行数据规格化。也就是将其缩至特定的范围之内,如:[0,10]。如:对于一 个顾客信息数据库中的年龄属性或工资属性,由于工资属性的取值比年龄属性的 取值要大许多,如果不进行规格化处理,基于工资属性的距离计算值显然将远超 过基于年龄属性的距离计算值,这就意味着工资属性的作用在整个数据对象的距 离计算中被错误地放大了。 规格化就是将一个属性取值范围投射到一个特定范围之内,以消除数值型属 性因大小不一而造成挖掘结果的偏差。规划化处理常常用于神经网络、基于距离 计算的最近邻分类和聚类挖掘的数据预处理。 。对于神经网络,采用规格化后的数据不仅有助于确保学习结果的正确性,而且也会帮助提高学习的速度。对于基于距离计算的挖掘,规格化方法可以帮助消除因属性取值范围不同而影响挖掘结果 的公正性。
三种规格化方法:
1.最大最小规格化方法 该方法对初始数据进行一种线性转换。设$ min{A} $和$ max{A} $为属性A的最小和最大值。最大最小规格化方法将属性A的一个值映射为$ v^{‘} $且有$ v^{‘} \in [newmin{A},newmax{A}] $,具体映射公式如下: $ v^{‘} = \frac{v-min{A}}{max{A}-min{A}} (new_max{A}-new_min_{A})+new_min_{A} $
2.零均值规格化方法。该方法是根据属性A的均值和偏差来对A进行规格化。属性A的v值可以通过以下计算公式获得其映射值$ v^{‘} $ $ v^{‘} = \frac{v-\bar A}{\sigma{A}} $
其中的$ \bar A $和$ \sigma{A} $分别为属性A的均值和方差。这种规格化方法常用于属性A最大值与最小值未知,或使用最大最小规格化方法时会出现异常数据的情况。
3.十基数变换规格化方法。 该方法通过移动属性A值的小数位置来达到规格化的目的。把移动的小数位取决于属性a绝对值的最大值。属性A的v值可以通过以下计算公式获得其映射值$ v^{‘} $。 $ v^{‘} = \frac{v}{10^{j}} $ 其中j为使$ \max(|v^{‘}|) \lt 1 $成立的最小值。
Ref:
1.统计学习方法-李航
2.数据挖掘导论
3.机器学习实战